#include "type.h"
#include "flash.h"
#include "main.h"
#include "gd32f30x.h"
#include "systick.h"

// 擦除函数
MI_BOOL gd32_flash_erase(MI_U32 start_addr, MI_U32 end_addr)
{
    int page_num = 0; 
    /* unlock the flash program/erase controller */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    /* erase the flash pages */
    while(start_addr < end_addr)
    {
        page_num = (start_addr - GD32_FLASH_BASE) / FLASH_PAGE_SIZE;

        fmc_page_erase((page_num * FLASH_PAGE_SIZE) + BOOT_START_ADDRESS);
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

        start_addr += FLASH_PAGE_SIZE;
    }

    /* lock the main FMC after the erase operation */
    fmc_lock();
    return MI_TRUE;
}


// 写函数
MI_BOOL gd32_flash_write(MI_U32 dest_addr, MI_U8 *src, MI_U32 Len)
{
    MI_U32 i = 0;

    fmc_unlock();

    for(i = 0; i < Len; i += 4)
    {
        /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
        be done by byte */
        int ret = fmc_word_program((MI_U32)(dest_addr+i), *(uint32_t*)(src+i));
        if(FMC_READY == ret)
        {
            fmc_flag_clear(FMC_FLAG_BANK0_END);
            fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
            fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
            /* Check the written value */
            if(*(uint32_t *)(src + i) != *(uint32_t*)(dest_addr+i))
            {
                /* Flash content doesn't match SRAM content */
                fmc_lock();  
                printf("write error 1\r\n");             
                return -1;
            }
        }
        else
        {
            fmc_lock(); 
            printf("write error2\r\n");           
            /* Error occurred while writing data in Flash memory */
            return ret;
        }
    }
    fmc_lock();            

    return 0;
}

// 读函数
MI_BOOL gd32_flash_read(MI_U32 dest_addr, MI_U8* buff, MI_U32 Len)
{

    MI_U32 i;
    for(i = 0; i < Len; i++)
    {
        buff[i] = *(__IO MI_U8*)(dest_addr + i);
    }
    /* Return a valid address to avoid HardFault */
    return 0;
}

MI_BOOL copy_download_to_app(void)
{
    MI_U8 buffer[1024] = {0};  //每次从download读1K字节，然后写入1K
    MI_U8 w_count = 0;
    MI_U16 w_len = sizeof(buffer);
    MI_U16 app_size = APP_SIZE;

    w_count = app_size / w_len;
    // 将App区域擦除
    gd32_flash_erase(APP_START_ADDRESS,APP_END_ADDRESS);
    printf("w_count == %d\r\n",APP_SIZE);
    printf("w_count == %d\r\n",w_len);
    printf("w_count == %d\r\n",w_count);

    for (int i = 0;i < w_count;i++)
    {
        gd32_flash_read(DOWNLOAD_START_ADDRESS + (w_len * i),buffer,w_len);
        delay_1ms(50);
        gd32_flash_write(APP_START_ADDRESS + (w_len * i),buffer,w_len);
        printf("update.............................%d [100] \r\n",((i+1) * 100 /w_count));
    }

    return MI_TRUE;
}
